package water.com.DbAuto;

import water.com.util.Built;
import water.com.util.ConfigurationReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.util.*;

public class AutoMakeTable {

    public static Map<String,String> registryMap;

    public static void makeTable() throws ClassNotFoundException, IOException {
        for(Map.Entry<String,String> entry: registryMap.entrySet()){
            Class<?> cl = Class.forName(entry.getValue());
            boolean hasAnnotation = cl.isAnnotationPresent(AutoTable.class);
            if(hasAnnotation){
                File file = new File("../WaterFramework/db/database/tables/"+ Built.toTableName(cl.getSimpleName())+".sql");
                String str = getTableStr(cl);
                try {
                    writeToFile(str,file);
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 将建表语句写入指定位置
     * @param str
     * @param file
     * @return
     */
    public static boolean writeToFile(String str,File file) throws IOException {
        FileOutputStream fileOutputStream = null;
        try {
            fileOutputStream = new FileOutputStream(file);
            fileOutputStream.write(str.getBytes(StandardCharsets.UTF_8));
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }finally {
            fileOutputStream.close();
        }
        return true;
    }

    /**
     * 生成建表语句
     * @param cl 类对象
     * @return 建表语句
     */
    public static String getTableStr(Class<?> cl){
        StringBuilder res = new StringBuilder();
        List<String> columns = new ArrayList<>();
        StringBuilder primaryKey = new StringBuilder();
        columns.add("CREATE TABLE "+Built.toTableName(cl.getSimpleName()));
        columns.add("(\n");
        Field[] fields = cl.getDeclaredFields();
        for(Field field:fields){
            StringBuilder colStr = new StringBuilder();
            colStr.append(Built.toColumnName(field.getName())).append(" ");
            if(field.isAnnotationPresent(ColumnDefine.class)){
                ColumnDefine columnDefine = field.getAnnotation(ColumnDefine.class);
                colStr.append(columnDefine.dataType()).append(" ");
                if(!columnDefine.defaultNull()){
                    colStr.append("not null ");
                }else {
                    colStr.append("default null ,\n");
                }
                if(columnDefine.autoIncrement()){
                    colStr.append("auto_increment").append(",\n");
                }
                if(columnDefine.primaryKey()){
                    primaryKey.append("primary key(").append(Built.toColumnName(field.getName())).append(")\n");
                }
            }else {
                colStr.append("varchar(20) ");
                colStr.append("default null ,\n");

            }
            columns.add(colStr.toString());
        }
        columns.add(primaryKey.toString());
        columns.add(");\n");
        for(String str:columns){
            res.append(str);
        }
        return res.toString();
    }

    public static void scanPackage(){
        registryMap = new HashMap<>();
        try{
            listTempFiles(new File("../WaterFramework/LibrarySystem/src"));
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 递归遍历源码文件夹，并将java文件筛选出来
     * 结息其信息，将其类名和包路径存储注册表中，方便后面根据类名获取类实例
     * @param  root 根目录
     */
    private static void listTempFiles(File root) {
        // 获取指定磁盘或文件夹的子列表
        File[] files = root.listFiles();
        if (files == null)
            return;
        for (File file : files) {
            if (file.isFile()) {
                if(file.getName().contains(".java")){
                    String beanName = file.getName().replace(".java","");
                    String[] packages = file.getPath().split("\\\\");
                    String packageStr = "";
                    for(int i = 6;i<packages.length;i++){
                        packageStr += packages[i]+".";
                    }
                    packageStr = packageStr.substring(0,packageStr.length()-1);
                    packageStr = packageStr.replace(".java","");
                    registryMap.put(beanName,packageStr);
                }
            } else if (file.isDirectory()){
                listTempFiles(file);
            }
        }
    }
}
